use anyhow::Result;
use iced::{Task, Element, Theme, Font};
use tracing::{info, error};

use cdb_core::DatabaseManager;
use cdb_gui::{CdbGui, Message as GuiMessage};
use cdb_ai::AiEngine;
use cdb_mcp::McpIntegration;

// Re-export for easier access
pub use iced;

pub struct CdbStudioApp {
    database_manager: DatabaseManager,
    gui: CdbGui,
    ai_engine: AiEngine,
    mcp_server: McpIntegration,
}

#[derive(Debug, Clone)]
pub enum Message {
    Gui(GuiMessage),
    DatabaseConnected(String),
    DatabaseError(String),
    AiResponse(String),
    McpRequest(String),
}

impl CdbStudioApp {
    pub async fn new(_config_path: String, database_url: Option<String>) -> Result<Self> {
        info!("Initializing CDB Studio application");
        
        // Initialize core components
        let database_manager = DatabaseManager::new().await?;
        let gui = CdbGui::new();
        let ai_engine = AiEngine::new().await?;
        let mcp_server = McpIntegration::new().await?;
        
        // Connect to database if provided
        if let Some(url) = database_url {
            info!("Connecting to database: {}", url);
            // TODO: Implement database connection
        }
        
        Ok(Self {
            database_manager,
            gui,
            ai_engine,
            mcp_server,
        })
    }
    
    pub fn run() -> Result<()> {
        info!("Starting CDB Studio GUI");

        // Use the new Iced 0.13 application builder pattern
        iced::application("CDB Studio", CdbStudioApp::update, CdbStudioApp::view)
            .theme(CdbStudioApp::theme)
            .window_size(iced::Size::new(1200.0, 800.0))
            .run_with(CdbStudioApp::new_for_iced)?;

        Ok(())
    }

    /// Create a new instance for Iced's run_with function
    fn new_for_iced() -> (Self, Task<Message>) {
        // Create a placeholder instance for now
        // In a real implementation, this would be properly initialized
        let app = Self {
            database_manager: DatabaseManager::new_sync(),
            gui: CdbGui::new(),
            ai_engine: AiEngine::new_sync(),
            mcp_server: McpIntegration::new_sync(),
        };

        (app, Task::none())
    }
}

impl CdbStudioApp {
    /// Update function for the new Iced 0.13 API
    fn update(&mut self, message: Message) -> Task<Message> {
        match message {
            Message::Gui(gui_msg) => {
                // Handle GUI messages that need app-level processing
                match &gui_msg {
                    GuiMessage::ConnectToDatabase => {
                        let config = self.gui.get_connection_config();
                        return Task::perform(
                            Self::connect_to_database(config),
                            |result| Message::Gui(GuiMessage::ConnectionResult(result))
                        );
                    }
                    GuiMessage::ExecuteQuery => {
                        let query = self.gui.current_query.clone();
                        if self.gui.is_connected {
                            return Task::perform(
                                Self::execute_query(query),
                                |result| Message::Gui(GuiMessage::QueryResultReceived(result))
                            );
                        }
                    }
                    GuiMessage::SendAiPrompt => {
                        let prompt = self.gui.ai_prompt.clone();
                        return Task::perform(
                            Self::process_ai_prompt(prompt),
                            |response| Message::Gui(GuiMessage::AiResponseReceived(response))
                        );
                    }
                    _ => {}
                }

                // Update GUI state
                self.gui.update(gui_msg);
                Task::none()
            }
            Message::DatabaseConnected(connection_info) => {
                info!("Database connected: {}", connection_info);
                Task::none()
            }
            Message::DatabaseError(error) => {
                error!("Database error: {}", error);
                Task::none()
            }
            Message::AiResponse(response) => {
                info!("AI response received: {}", response);
                Task::none()
            }
            Message::McpRequest(request) => {
                info!("MCP request received: {}", request);
                Task::none()
            }
        }
    }

    /// View function for the new Iced 0.13 API
    fn view(&self) -> Element<Message> {
        self.gui.view().map(Message::Gui)
    }

    /// Theme function for the new Iced 0.13 API
    fn theme(&self) -> Theme {
        Theme::TokyoNight
    }

    /// Connect to database (async task)
    async fn connect_to_database(config: cdb_core::database::ConnectionConfig) -> Result<String, String> {
        use cdb_core::database::DatabaseConnection;

        match DatabaseConnection::test(&config).await {
            Ok(_) => Ok(format!("Connected to {} on {}:{}",
                config.database_type.display_name(),
                config.host,
                config.port)),
            Err(e) => Err(format!("Connection failed: {}", e)),
        }
    }

    /// Execute query (async task)
    async fn execute_query(query: String) -> Result<String, String> {
        // For now, return a mock result
        // In a real implementation, this would use the database manager
        tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;

        if query.trim().is_empty() {
            return Err("Query cannot be empty".to_string());
        }

        // Mock query execution
        let result = if query.trim().to_lowercase().starts_with("select") {
            format!("Query executed successfully!\n\nResults:\nid | name\n1  | John Doe\n2  | Jane Smith\n\nRows returned: 2\nExecution time: 45ms")
        } else if query.trim().to_lowercase().starts_with("insert") {
            format!("INSERT executed successfully!\n\nRows affected: 1\nExecution time: 23ms")
        } else if query.trim().to_lowercase().starts_with("update") {
            format!("UPDATE executed successfully!\n\nRows affected: 1\nExecution time: 31ms")
        } else if query.trim().to_lowercase().starts_with("delete") {
            format!("DELETE executed successfully!\n\nRows affected: 1\nExecution time: 28ms")
        } else {
            format!("Query executed successfully!\n\nExecution time: 15ms")
        };

        Ok(result)
    }

    /// Process AI prompt (async task)
    async fn process_ai_prompt(prompt: String) -> String {
        // Mock AI processing
        tokio::time::sleep(tokio::time::Duration::from_millis(500)).await;

        if prompt.to_lowercase().contains("select") || prompt.to_lowercase().contains("find") {
            format!("Based on your request '{}', here's a suggested SQL query:\n\nSELECT * FROM users WHERE name LIKE '%{}%';\n\nThis query will find all users whose names contain the specified text.", prompt, prompt.split_whitespace().last().unwrap_or(""))
        } else if prompt.to_lowercase().contains("create") || prompt.to_lowercase().contains("table") {
            format!("For creating a table based on '{}', consider this SQL:\n\nCREATE TABLE example_table (\n    id SERIAL PRIMARY KEY,\n    name VARCHAR(255) NOT NULL,\n    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n);", prompt)
        } else {
            format!("I understand you want to: {}\n\nHere are some SQL suggestions:\n- Use SELECT for querying data\n- Use INSERT for adding new records\n- Use UPDATE for modifying existing data\n- Use DELETE for removing records\n\nWould you like me to help you write a specific query?", prompt)
        }
    }
}
